﻿#pragma once 
#include <iostream>
#include <cassert>
#include <mutex>
#include "ObjectPool.hpp"
#ifdef _WIN64
	typedef unsigned long long ;
#elif _WIN32
	typedef size_t PAGE_ID;
#endif 

// 先描述
struct Span
{
	// pageid和npage就能描述清楚一个span的大小和起始地址！！！
	PAGE_ID _pageid = 0; // 大块内存起始页的页号 [和起始地址有关 >> 13得到页号]不是地址
	size_t _npage = 0; // 页的数量，对应映射关系。[1,128];
	
	// 链式结构
	Span* _next = nullptr;
	Span* _prev = nullptr;

	size_t _usecount = 0; // 切好⼩块内存，被分配给thread cache的计数
	size_t _objsize = 0; // 当前span管理的对象大小
	void* _freelist = nullptr; 

	bool _isuse = false; // 当前的Span是否被使用
};

// 再组织
class Spanlist
{
public:
	Spanlist() 
	{
		static ObjectPool<Span> objectSpan;
		_head = objectSpan.New();
		_head->_next = _head;
		_head->_prev = _head;
	}
	Span* Begin()
	{
		return _head->_next;
	}

	Span* End()
	{
		return _head;
	}
	// 头插
	void Insert(Span* pos, Span* newnode)
	{
		assert(pos && newnode && pos->_prev);
		Span* prev = pos->_prev;
		prev->_next = newnode;
		newnode->_prev = prev;
		newnode->_next = pos;
		pos->_prev = newnode;
	}
	Span* PopFront()
	{
		Span* span = Begin();
		Erase(Begin());
		return span;
	}

	void PushFront(Span* newnode)
	{
		Insert(Begin(), newnode);
	}

	void Erase(Span* span)
	{
		assert(span);
		Span* prev = span->_prev, * next = span->_next;
		prev->_next = next;
		next->_prev = prev;
		span->_next = nullptr;
		span->_prev = nullptr;
		// 这里不用真删,不用真的给系统，而是后面交给pagecache
	}
	bool Empty()
	{
		return Begin() == End();
	}
	
	~Spanlist()
	{
		static ObjectPool<Span> objectSpan;
		objectSpan.Delete(_head);  // 使用对象池释放
		_head = nullptr;
	}
private:
	Span* _head = nullptr;
public:
	std::mutex _lock; // 桶锁
};